// 底部播放器组件
<template>
  <div class="mini-player" id="mini-player">
    <!-- song -->
    <div class="song">
      <template v-if="hasCurrentSong">
        <div @click="togglePlayerShow" class="img-wrap">
          <div class="mask"></div>
          <img v-lazy="$utils.getImgUrl(currentSong.img, 80)" class="blur" />
          <div class="player-control">
            <Icon :size="24" :type="playControlIcon" color="white" />
          </div>
        </div>
        <div class="content">
          <div class="top">
            <p class="name">{{ currentSong.name }}</p>
            <p class="split">-</p>
            <p class="artists">{{ currentSong.artistsText }}</p>
          </div>
          <div class="time">
            <span class="played-time">
              {{ $utils.formatTime(currentTime) }}
            </span>
            <span class="split">/</span>
            <span class="total-time">
              {{ $utils.formatTime(currentSong.duration / 1000) }}
            </span>
          </div>
        </div>
      </template>
    </div>
    <!-- 控制台 -->
    <div class="control">
      <Icon @click="prev" :size="24" class="icon" type="prev" />
      <el-popover :value="isPlayErrorPromptShow" trigger="manual" placement="top" width="160">
        <p>请点击开始播放</p>
        <div @click="togglePlaying" class="play-icon" slot="reference">
          <Icon :size="24" :type="playIcon" />
        </div>
      </el-popover>
      <Icon @click="next" :size="24" class="icon" type="next" />
    </div>
    <!-- 右侧按钮部分 -->
    <div class="mode">
      <!-- 分享按钮 -->
      <Share :shareUrl="shareUrl" class="mode-item" v-show="hasCurrentSong" />
      <!-- 播放模式 -->
      <el-popover placement="top" trigger="hover" width="160">
        <p>{{ playModeText }}</p>
        <Icon
          @click="onChangePlayMode"
          :size="20"
          :type="modeIcon"
          class="mode-item"
          slot="reference"
        />
      </el-popover>
      <!-- 播放列表 -->
      <el-popover :value="isPlaylistPromptShow" placement="top" trigger="manual" width="160">
        <p>已更新歌单</p>
        <Icon
          @click="togglePlaylistShow"
          :size="20"
          class="mode-item"
          slot="reference"
          type="playlist"
        />
      </el-popover>
      <!-- 音量 -->
      <div class="volume-item">
        <Volume :volume="volume" @volumeChange="onVolumeChange" />
      </div>
      <!-- github -->
      <Icon @click="goGithub" :size="20" class="mode-item" type="github" />
    </div>
    <!-- 播放进度条 -->
    <div class="progress-bar-wrap">
      <ProgressBar
        :disabled="!hasCurrentSong"
        :percent="playedPercent"
        @percentChange="onProgressChange"
      />
    </div>
    <!-- audio -->
    <audio
      :src="currentSong.url"
      @canplay="ready"
      @ended="end"
      @timeupdate="updateTime"
      @error="error"
      ref="audio"
    ></audio>
  </div>
</template>

<script>
import { mapState, mapMutations, mapGetters, mapActions } from '@/store/helper/music'
import Storage from 'good-storage'
import Share from '@/components/share'
import { VOLUME_KEY, playModeMap, isDef } from '@/utils'

const DEFAULT_VOLUME = 0.75
export default {
  data() {
    return {
      isPlayErrorPromptShow: false,
      songReady: false,
      volume: Storage.get(VOLUME_KEY, DEFAULT_VOLUME)
    }
  },
  mounted() {
    this.audio.volume = this.volume
  },
  methods: {
    // 更新播放状态
    togglePlaying() {
      // 当前未播放歌曲则直接退出
      if (!this.currentSong.id) {
        return
      }
      this.setPlayingState(!this.playing)
    },
    ready() {
      this.songReady = true
    },
    async play() {
      if (this.songReady) {
        try {
          await this.audio.play()
          if (this.isPlayErrorPromptShow) {
            this.isPlayErrorPromptShow = false
          }
        } catch (error) {
          // 提示用户手动播放
          this.isPlayErrorPromptShow = true
          this.setPlayingState(false)
        }
      }
    },
    pause() {
      this.audio.pause()
    },
    updateTime(e) {
      const time = e.target.currentTime
      this.setCurrentTime(time)
    },
    prev() {
      if (this.songReady) {
        this.startSong(this.prevSong)
      }
    },
    next() {
      if (this.songReady) {
        this.startSong(this.nextSong)
      }
    },
    end() {
      this.next()
    },
    error() {
      this.songReady = true
      this.next()
    },
    onProgressChange(percent) {
      this.audio.currentTime = this.currentSong.durationSecond * percent
      this.setPlayingState(true)
    },
    onVolumeChange(percent) {
      this.audio.volume = percent
      Storage.set(VOLUME_KEY, percent)
    },
    onChangePlayMode() {
      const modeKeys = Object.keys(playModeMap)
      const currentModeIndex = modeKeys.findIndex(key => playModeMap[key].code === this.playMode)
      const nextIndex = (currentModeIndex + 1) % modeKeys.length
      const nextModeKey = modeKeys[nextIndex]
      const nextMode = playModeMap[nextModeKey]
      this.setPlayMode(nextMode.code)
    },
    togglePlaylistShow() {
      this.setPlaylistShow(!this.isPlaylistShow)
    },
    togglePlayerShow() {
      this.setPlayerShow(!this.isPlayerShow)
    },
    goGithub() {
      window.open('https://github.com/uyingchuan')
    },

    ...mapMutations([
      'setCurrentTime',
      'setPlayingState',
      'setPlayMode',
      'setPlaylistShow',
      'setPlayerShow'
    ]),
    ...mapActions(['startSong'])
  },
  watch: {
    currentSong(newSong, oldSong) {
      // 清空了歌曲
      if (!newSong.id) {
        this.audio.pause()
        this.audio.currentTime = 0
        return
      }
      // 单曲循环
      if (oldSong && newSong.id === oldSong.id) {
        this.setCurrentTime(0)
        this.audio.currentTime = 0
        this.play()
        return
      }
      this.songReady = false
      if (this.timer) {
        clearTimeout(this.timer)
      }
      this.timer = setTimeout(() => {
        this.play()
      }, 1000)
    },
    playing(newPlaying) {
      this.$nextTick(() => {
        newPlaying ? this.play() : this.pause()
      })
    }
  },
  computed: {
    hasCurrentSong() {
      return isDef(this.currentSong.id)
    },
    playIcon() {
      return this.playing ? 'pause' : 'play'
    },
    currentMode() {
      return playModeMap[this.playMode]
    },
    modeIcon() {
      return this.currentMode.icon
    },
    playModeText() {
      return this.currentMode.name
    },
    audio() {
      return this.$refs.audio
    },
    // 播放的进度条百分比
    playedPercent() {
      const { durationSecond } = this.currentSong
      return Math.min(this.currentTime / durationSecond, 1) || 0
    },
    playControlIcon() {
      return this.isPlayerShow ? 'shrink' : 'open'
    },
    shareUrl() {
      return `${window.location.origin}?shareMusicId=${this.currentSong.id}`
    },
    ...mapState([
      'currentSong',
      'currentTime',
      'playing',
      'playMode',
      'isPlaylistShow',
      'isPlaylistPromptShow',
      'isPlayerShow'
    ]),
    ...mapGetters(['prevSong', 'nextSong'])
  },
  components: { Share }
}
</script>

<style lang="scss" scoped>
.mini-player {
  // position: relative;
  position: fixed;
  left: 0;
  bottom: 0;
  right: 0;
  display: flex;
  justify-content: space-between;
  height: $mini-player-height;
  background: var(--body-bgcolor);
  padding: 8px 16px 8px 24px;
  z-index: $mini-player-z-index;

  .song {
    flex: 4;
    display: flex;
    overflow: hidden;

    .img-wrap {
      position: relative;
      margin-right: 8px;
      border-radius: 6px;
      overflow: hidden;
      cursor: pointer;
      @include img-wrap(40px);

      img {
        &.blur {
          filter: blur(2px);
        }
      }

      .player-control {
        @include abs-center;
      }

      .mask {
        @include abs-stretch;
        background: rgba($color: #000000, $alpha: 0.2);
      }
    }

    .content {
      flex: 1;
      overflow: hidden;
      display: flex;
      flex-direction: column;
      justify-content: space-around;

      .top {
        display: flex;
        align-items: flex-end;
        white-space: nowrap;

        .name {
          color: var(--font-color-white);
          @include text-ellipsis;
        }

        .split {
          font-size: $font-size-xs;
          @include text-ellipsis;
        }
      }

      .time {
        font-size: $font-size-xs;
        color: var(--font-color-grey);

        .split {
          margin: 0 4px;
        }
      }
    }
  }

  .control {
    position: absolute;
    height: 100%;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 200px;
    @include flex-center();

    .icon {
      color: $theme-color;
    }

    .play-icon {
      background: $theme-color;
      width: 45px;
      height: 45px;
      margin: 0 16px;
      @include flex-center;
      border-radius: 50%;

      i {
        color: $white;
      }

      .icon-play {
        transform: translateX(1px);
      }
    }
  }

  .mode {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex: 6;

    .mode-item {
      display: block;
      margin-right: 16px;
      width: 22px;
    }

    .volume-item {
      margin-right: 22px;

      .block {
        width: 160px;
      }
    }
  }

  .progress-bar-wrap {
    position: absolute;
    left: 0;
    right: 0;
    top: -14px;
  }
}
</style>
